﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data;
using GestionCegep.Objects;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;


namespace GestionCegep
{
    public class Departement : PersistentObject
    {
        private static Departement oldDepartement = new Departement();

        // Différentes requetes a la base de donnees pour la gestion des departements
        private const string selectQuery = "SELECT ID, NOM FROM DEPARTEMENT";
        private const string lockQuery = "LOCK TABLE DEPARTEMENT IN EXCLUSIVE MODE";
        private const string insertQuery = "INSERT INTO DEPARTEMENT(NOM) VALUES('{0}') RETURNING ID INTO :myOutputParameter";
        private const string updateQuery = "UPDATE DEPARTEMENT SET NOM = '{0}' WHERE ID = {1}";
        private const string deleteQuery = "DELETE FROM DEPARTEMENT WHERE ID = {0}";

        private int id;     // Identifiant unique du departement
        private string nom; // Nom du departement

        // Constructeur d'un departement
        private Departement(int id, string nom, bool isNew = false)
        {
            this.id = id;
            this.nom = nom;
            this.isNew = isNew;
        }

        public Departement()
        {
            isNew = true;
        }

        public Departement(int id, string nom)
        {
            this.id = id;
            this.nom = nom;
            this.isNew = true;
        }

        public int Id { get { return id; } }
        public string Nom { get { return nom; } set { nom = value; isModified = true; } }

        // Insertion d'un departement dans la base de données
        public override void InsertIntoDataBase(OracleConnection oracleConnection, DataStore dataStore)
        {
            OracleDecimal ora_dec;
            OracleCommand command; // Commande Oracle
            try
            {
                command = oracleConnection.CreateCommand(); // Creation de la commande
                command.CommandText = lockQuery; // Vérouillage de la table
                command.ExecuteNonQuery();

                command.CommandText = String.Format(insertQuery, nom);
                command.Parameters.Add("myOutputParameter", OracleDbType.Decimal, ParameterDirection.ReturnValue); // Ajout d'un parametre a la requete
                command.ExecuteNonQuery();

                // Recuperation du dernier identifiant inserer dans la base de donnees
                ora_dec = (OracleDecimal)command.Parameters["myOutputParameter"].Value;
                id = ora_dec.ToInt32();

                // Journalisation de l'insertion
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Defaire, String.Format(deleteQuery, id));
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Refaire, String.Format(insertQuery, nom));

                dataStore.CurrentTransaction.Commit(); // Confirmation de la transaction

                dataStore.Departements.Add(this); // Ajout du departement a la liste des departements
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        // Vérouillage pour la mise a jour
        public override void LockForUpdate(OracleConnection OracleConnection)
        {
            try
            {
                OracleCommand command = OracleConnection.CreateCommand(); // Creation de la commande Oracle
                command.CommandText = selectQuery + " WHERE ID = " + id + " FOR UPDATE"; // Verouillage pour la mise a jour
                command.ExecuteScalar();

                oldDepartement.id = id;
                oldDepartement.nom = nom;
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        // Mise a jour dans la base de donnees
        public override void UpdateIntoDataBase(MyOracleTransaction currentTransaction)
        {
            try
            {
                OracleCommand command = currentTransaction.Connection.CreateCommand(); // Creation de la commande Oracle
                command.Transaction = currentTransaction.OracleTransaction;
                command.CommandText = String.Format(updateQuery, nom, id); // Mise a jour dans la base de donnees
                command.ExecuteNonQuery();

                // Journalisation de la transaction
                currentTransaction.PushLogToBD(LogActions.Defaire, String.Format(updateQuery, oldDepartement.nom, id));
                currentTransaction.PushLogToBD(LogActions.Refaire, command.CommandText);

                currentTransaction.Commit(); // Confirmation de la transaction
            }
            catch (OracleException exception)
            {
                nom = oldDepartement.nom;
                throw exception;
            }
        }

        // Suppresion dans la base de donnees
        public override void DeleteFromDataBase(OracleConnection OracleConnection, DataStore dataStore)
        {
            OracleCommand command;
            try
            {
                command = OracleConnection.CreateCommand(); // Creation d'une commande Oracle
                command.CommandText = lockQuery; // Vérouillage de la table pour la suppresion
                command.ExecuteNonQuery();

                command.CommandText = String.Format(deleteQuery, id); // Suppression dans la base de données
                command.ExecuteNonQuery();

                // Journalisation de la modification
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Defaire, String.Format(insertQuery, nom));
                dataStore.CurrentTransaction.PushLogToBD(LogActions.Refaire, command.CommandText);
                
                dataStore.CurrentTransaction.Commit(); // Confirmation de la transaction
                dataStore.Departements.Remove(this); // On supprime le departement de la liste des departements
            }
            catch (OracleException exception)
            {
                throw exception;
            }
        }

        // Balayage de la table cours pour obtenir toutes les informations
        public static List<Departement> GetDepartementsFromDataBase(OracleConnection OracleConnection)
        {
            List<Departement> departements = new List<Departement>(); // Liste des departements

            try
            {
                OracleCommand command = OracleConnection.CreateCommand(); // Creation de la commande Oracle
                command.CommandText = selectQuery;
                OracleConnection.Open();
                OracleDataReader reader = command.ExecuteReader(); // Execution de la requete select

                // Tant qu'il y a des donnees dans la table Departement
                while (reader.Read())
                {
                    Departement departement = new Departement(Convert.ToInt32(reader["ID"].ToString()),
                                                                reader["NOM"].ToString(),
                                                                false);
                    departements.Add(departement); // Ajout de tout les departements a la liste des departements
                }
                OracleConnection.Close(); // Fermeture de la connexion
            }
            catch (Exception exception)
            {
                throw exception;
            }

            return departements; // On retourne les departements pour le remplissable du DataGridView
        }
    }
}
